home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine CD 1995 / Archive Magazine CD 1995.iso / discs / pipeline / abacus / p_line / Custom04 / ReadMe < prev    next >
Encoding:
Text File  |  1992-11-10  |  14.7 KB  |  291 lines

  1. %OP%VS4.13 (28-Apr-92), Gerald L Fitton, R4000 5966 9904 9938 
  2. %OP%DP0
  3. %OP%IRY
  4. %OP%PL0
  5. %OP%HM0
  6. %OP%FM0
  7. %OP%BM0
  8. %OP%LM4
  9. %OP%PT1
  10. %OP%PDPipeLine
  11. %OP%WC1014,2262,232,1748,0,0,0,0
  12. %CO:A,72,72%
  13. %C%Repetition
  14. %C%by Gerald L Fitton
  15. Keywords:
  16. Repetition Fitton
  17.  
  18. This is the fourth tutorial article in the series which I hope will 
  19. help you with PipeDream 4's custom functions.  The first three articles 
  20. were on earlier PipeLine 4 discs in the directories Custom01, Custom02 
  21. and Custom03.
  22.  
  23. If you wish to write custom functions then you need to learn '4ProL', 
  24. the PipeDream 4 custom function programming language.  Designing a new 
  25. language such as '4ProL' is always a compromise.
  26.  
  27. The compromise is between:
  28.  
  29. (a) Including commands which provide the flexibility needed to carry 
  30.     out complex or intricate processes quickly and
  31.  
  32. (b) Inherent constraints which encourage those 'good' programming 
  33.     techniques needed to facilitate debugging and program improvements.
  34.  
  35. The compromise is to learn a set of conventions (a sub set of the 
  36. constraints of the language) which encourage 'good' programming and to 
  37. aim to write 'well written' programs.  Only after becoming master of 
  38. the conventions should you break them knowing that you need speed or 
  39. efficiency which can not be achieved by sticking rigidly to those 
  40. (advised) conventions.
  41.  
  42. The conventions which I am recommending in this series have been 
  43. discussed with and approved of by Colton Software.  This series is 
  44. intended to help you learn '4Prol' and a set of workable conventions.  
  45. The earlier articles covered the topics Sequence (calling a function 
  46. and returning a result), Conditional execution (If), the use of 
  47. Parameters and Named variables and the constraints and conventions 
  48. associated with their use.
  49.  
  50. In this article, in addition to expanding on the topic of variables, I 
  51. introduce the topic of Repetition using For - Next loops using as my 
  52. main example a fixed term, fixed interest rate loan.  There is a second 
  53. example in which the interest rate and the repayments can be changed 
  54. from year to year.
  55.  
  56. The Fixed Term Fixed Interest Rate Loan
  57. Most Hire Purchase loans are of this type.  Double click on the file 
  58. [Repayment] and both the file [Repayment] and the custom function file 
  59. which it uses, [c_Balance], is also loaded into memory and displayed 
  60. on the screen.
  61.  
  62. Look at row 6 of [Repayment].  You can change the 'Initial Balance' 
  63. (the amount borrowed), the number of years, the annual interest rate 
  64. and the size of the annual repayment.  The 'Final Balance' is 
  65. calculated by the custom function "final_balance".  It is the amount 
  66. still owing at the end of the last year.  The assumption made is the 
  67. usual one that the interest is charged at the beginning of each year 
  68. and that the first repayment is made at the end of the first year.
  69.  
  70. The custom function calculates the interest to be added at the start of 
  71. the year and adds it to the outstanding amount.  The amount of the 
  72. repayment is subtracted and the result is the amount owing at the start 
  73. of the following year.
  74.  
  75. Variables
  76. Let me continue (from an earlier article) my discussion of variables.  
  77. I know that there are many different ways of classifying variables.  
  78. The one I shall use is the classification into 'global', 'parameters' 
  79. and 'local' variables.  They are so named because of the way in which 
  80. they are used.
  81.  
  82. Local Variables
  83. An example of this category of variable is the interest charged during 
  84. any one particular year.  It is the variable "interest_charged" 
  85. declared in slot [c_Balance]A11.  Outside the custom function there is 
  86. no point in knowing its value.  Such a variable is called 'local' 
  87. because it is useful only within the context (the locality) of the 
  88. custom function.  It is considered bad practice (and in some 
  89. programming languages impossible) to use a value taken by a local 
  90. variable outside the custom function which uses it.
  91.  
  92. If, within a custom function, "function01", there is a slot which calls 
  93. the same custom function, "function01", then there will be two versions 
  94. of the same custom function in existence at the same time.  It is 
  95. essential that the two different values of the local variable (held 
  96. within the two separate versions) are not confused.  4ProL (the 
  97. PipeDream programming language) supports such multiple existences of 
  98. local variables.  The technique of 'function01' calling itself is 
  99. called 'recursion'.  4ProL supports recursion.  In a future tutorial I 
  100. will show how to use 4ProL to calculate the "factorial" of an integer 
  101. using a custom function "factorial" recursively.  For now let me say 
  102. that, if a variable is useful only within a custom function then it 
  103. should be declared as a local variable and given a name.  You will see 
  104. that I have declared three such local variables in slots 
  105. [c_Balance]A10, [c_Balance]A11 and [c_Balance]A12.  They are the 
  106. balance owing at the beginning of a year ("starting_balance"), the 
  107. interest charged during the year ("interest_charged"), and the balance 
  108. owing at the end of the year ("end_balance").
  109.  
  110. Some of you who are into programming, looking a little further down the 
  111. custom function to [c_Balance]A17, will see a variable "loop_counter" 
  112. and wonder why I haven't declared that as a local variable!  In my view 
  113. it has to be a local variable so I ought to declare it.  Well, I don't 
  114. know if you'd consider it a 'bug' or not but, if you do declare loop 
  115. counters as local variables then, in certain circumstances, you get an 
  116. error message.  Try to run [Loop].  It calls the custom function 
  117. "[c_Loop]test_loop_counter".  I haven't worked out exactly what's going 
  118. on but I don't like it.  Anybody got any ideas?
  119.  
  120. Parameters
  121. Another category of variable is a 'parameter'.  The parameter called
  122. "no_of_years" which appears in slot [c_Balance]A7 is 'passed' to the 
  123. custom function from [Repayment]D6 as the third argument of the custom 
  124. function.  There is little temptation to change the value of this 
  125. particular parameter from within the custom function.  However, some 
  126. programmers encountering the 'repayment' problem for the first time 
  127. might be tempted to change the "initial_balance" (another parameter 
  128. passed to [c_Balance]) at the start of each of the years.  A convention 
  129. of good programming is never to change the value of a parameter from 
  130. within the custom function to which that parameter is passed.  An even 
  131. worse practice I have seen on occasions is to change a parameter from 
  132. within a 'sub routine' called by the custom function.
  133.  
  134. The conventional way to handle the requirement to 'increment the year' 
  135. is to declare some local variables and 'pass' the initial values of 
  136. those local variables to the custom function as parameters.  That is 
  137. what I have done in this example.
  138.  
  139. Global Variables
  140. A 'global' variable is one which exists outside the custom function.  
  141. Let me be as honest as I can be here.  Many programmers do change the 
  142. values of global variables from within 'sub routines' (in 4ProL 'sub 
  143. routines' are custom functions).  I don't recommend it because I think 
  144. it unnecessary and I believe that it can cause difficulties for other 
  145. people who come along later, want to use the custom function and so 
  146. they try to disentangle the program.
  147.  
  148. I believe that global values should not be used within custom 
  149. functions.  Let me give you a good reason why.  I have a phrase for 
  150. custom functions which contain only parameters and local variables.  I 
  151. call them 'stand alone' custom functions because you can call them from 
  152. 'anywhere' (ie from any spreadsheet) - you can build up a library of 
  153. such custom functions and they will always 'work' because 4ProL will 
  154. not get confused about the value any variable has at any stage.
  155.  
  156. It is a temptation to use set_value([Calling_Doc]slot,[Custom_Fn]slot]) 
  157. within a custom function to 'export' data from a custom function back 
  158. into the calling document.  The slot [Calling_Doc]slot is a 'global' 
  159. variable so far as the custom function is concerned.  Including the 
  160. name of the calling document inside the custom function 'spoils' the 
  161. generality of the custom function because it can be used only with a 
  162. calling document of the name used.  Some innocent person might try to 
  163. use such a custom function from one of their own calling documents and, 
  164. because the custom function is not 'self contained', then an error will 
  165. be returned.  Instead of using set_value(,) within the custom function 
  166. I recommend that you use set_value(slot,"custom_function") within the 
  167. calling document.  That way global variables are not required!  Enough 
  168. of this for now - you'll have wait for another tutorial.
  169.  
  170. Repetition
  171. A repeated sequence of commands is called a 'loop'.  In 4ProL you can 
  172. repeat a sequence of commands in three ways.  The first method, the one 
  173. used in this tutorial, repeats the sequence a preset number of times.  
  174. The other two methods involve conditional execution of the 'loop' an 
  175. indeterminate number of times.
  176.  
  177. In this example the commands which are executed a fixed number of times 
  178. can be found in [c_Balance]A18, [c_Balance]A19 and [c_Balance]A20.  The 
  179. named local variable "starting_balance" is set to the "end_balance" 
  180. from the previous period.  The "interest_charged" is calculated, added 
  181. to the amount owing and the repayment (a parameter, hence the use of 
  182. the @@ sign in @@repayment) is added to calculate the "end_balance" at 
  183. the end of the period.
  184.  
  185. For - Next
  186. The loop is bracketed by the commands for(,,) in [c_Balance]A17 at the 
  187. beginning of the loop and terminated by next in [c_Balance]A21.
  188.  
  189. The arguments of for(,,) are the "loop_counter", a named variable which 
  190. is initialised by the for("loop_counter",,) command.  The second 
  191. argument (in this case the number 1) is the starting value of the 
  192. "loop_counter" and the third argument (in this case the parameter 
  193. @@no_of_years) is the final value of the "loop_counter".  You can use a 
  194. fourth parameter, the amount by which the "loop_counter" is incremented 
  195. by the next command at the end of each loop.  The default (used in this 
  196. example) is a step (increment) of 1.
  197.  
  198. Indentation
  199. In order to improve readability it is conventional to indent the 
  200. commands which are within the loop.  You can do this by typing a space 
  201. (with the space bar) in the function line at the start of the command.  
  202. I have indented the three commands which are within the loop.
  203.  
  204. Nested Loops
  205. This example does not include loops within loops but, when such a 
  206. construction is used you must use different names for each of the 
  207. separate loop counter.  It is conventional in nested loops to further 
  208. indent the 'inner' loop (by two spaces for the second, inner, loop 
  209. and three spaces for a third loop inside the second one) in order that 
  210. the reader (who didn't write the custom function) can recognise 
  211. quickly where each loop begins and ends.
  212.  
  213. Using Arrays
  214. I shall deal with this concept in two stages.  The first stage is 
  215. 'passing' arrays to custom functions.  The second is 'returning' an 
  216. array from a custom function to a calling document.  Only the first 
  217. part (passing arrays to custom functions) is contained within this 
  218. tutorial.  The second part will have to wait!
  219.  
  220. Essentially an array is a set of many values which can be contained 
  221. within one slot or known by one name.  If you have not already done so 
  222. then I suggest that you have a look at the tutorials on 'Arrays from 
  223. the Beginning' which are in the directories Array1, Array2, etc (eg on 
  224. the 4Sight and 4Intro discs).
  225.  
  226. Have a look at the slots [Repayment]A12E18 and [c_Balance]A29A49.  You 
  227. can change any of the values of the interest rates, [Repayment]C14C18, 
  228. and the repayments, [Repayment]D14D18.  The final balance will be 
  229. recalculated by the custom function [c_Balance]final_balance_02 which 
  230. you will find in [Repayment]E18.
  231.  
  232. The set of interest rates is passed to the custom function as the range 
  233. [Balance]C14C18 and received by the custom function as the parameter 
  234. "interest:array".  The appropriate interest rate for the year is 
  235. extracted by the use of the function index(,,) in slot [c_Balance]A43.  
  236. Similarly, the repayment schedule is passed as an array and the 
  237. individual repayment extracted by the index(,,) function in slot 
  238. [c_Balance]A45 of the custom function.
  239.  
  240. Changing a Single Value in an Array
  241. One reason why I am not tackling the return of an array from a custom 
  242. function to the calling document is that, with an earlier version of 
  243. PipeDream 4 I had problems writing to a single value of an array.  The 
  244. command set_value(index(array,col_offset,row_offset),value) failed to 
  245. 'work' as I had hoped and expected so I used a long drawn out 'work 
  246. around' which used an expansion of the array into slots containing 
  247. single values.  A few tests I have  just tried on version 4.13 of 
  248. indicates that the set_value(index(,,),) technique does work now.  My 
  249. carefully worked out tutorial is now inelegant to say the least so I 
  250. have scrapped it.
  251.  
  252. Another reason for not including an example of returning arrays from 
  253. custom functions is that I am still working on the rational of using 
  254. the function deref(slot) when arrays are passed to custom functions 
  255. expecting (and returning) single values.  Don't misunderstand me, I 
  256. have written quite a few applications of that type which 'work' - but 
  257. only when I use deref(slot) - however, I'm not satisfied that I know 
  258. exactly what's happening when they do work!
  259.  
  260. Summary
  261. There are three categories of variable - local, parameters and global.  
  262. Values of parameters should not be changed within a custom function.  
  263. Local variables should be irrelevant outside the custom function in 
  264. which they are used.  I don't like using global variables within custom 
  265. functions (but some programmers would disagree with me).
  266.  
  267. What I have called a 'self contained' custom function is one in which 
  268. the only variables are parameters and local variables.  Such custom 
  269. functions can be use by anybody from any calling document (just like 
  270. anybody can use the square root function) without knowing why it works.  
  271. Furthermore, 4ProL will not get confused if the same name is used for 
  272. local variables within different custom functions which are all 
  273. 'working simultaneously'.
  274.  
  275. An array can be passed to a custom function as a named parameter.  If 
  276. the custom function is expecting an array then it will use the array as 
  277. an array.  I have not described how a custom function treats an array 
  278. when it expects a single value - that's for another tutorial.
  279.  
  280. A sequence of commands can be repeated a pre determined number of times 
  281. using a for(,,) - next loop.  The "loop_counter" is a local variable 
  282. but should not be declared nor initialised separately from its first 
  283. appearance in the for(,,) command.
  284.  
  285. It is conventional to indent the set of commands which are repeated so 
  286. that the structure can be 'read' more easily.
  287.  
  288. There are other methods of constructing a repetitive sequence in which 
  289. the number of repetitions is not fixed but is evaluated during the 
  290. execution of the loop.  I shall explain them in a future tutorial.
  291.